﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using XLua;
using XLua.LuaDLL;

public class LuaManager : MonoSingleton<LuaManager>
{
    private static string LuaScriptsPath = "LuaScripts/";
    private static string LuaBytesPath = "LuaBytes/";
    private static string bytesEx = ".bytes";
    private static string bytesAsset = "asset";
    private static string luaEx = ".lua";
    private LuaEnv luaEnv = new LuaEnv();

    protected override void Init()
    {
        luaEnv.AddLoader(CustomLoader);
        luaEnv.AddBuildin("protobuf.c", LuaDLL.Lua.LoadProtobuf);
    }
    
    private string GetScriptsFullPath(string luaPath)
    {
        string realPath = String.Empty;
        realPath = luaPath.Replace(".", "/") + luaEx;
        realPath = Path.Combine(LuaScriptsPath, realPath);
        realPath = Path.Combine(Application.dataPath, realPath);
        return realPath;
    }
    
    private string GetScriptsAssetPath(string luaPath)
    {
        var list = luaPath.Split('.');
        var luaName = list[list.Length - 1];
        StringBuilder realPath = new StringBuilder();
        realPath.Append(LuaBytesPath.ToLower().Replace("/", "."))
;        for (int i = 0; i < list.Length - 1; ++i)
        {
            realPath.Append(list[i].ToLower());
            realPath.Append(".");
        }
        realPath.Append(bytesAsset);
        realPath.Append("/");
        realPath.Append(luaName.ToLower());
        realPath.Append(bytesEx);
        return realPath.ToString();
    }

    private byte[] CustomLoader(ref string filepath)
    {
#if UNITY_IOS || UNITY_ANDROID || UNITY_IPHONE
        var textAsset = ResourceManager.Instance.LoadAsset(GetScriptsAssetPath(filepath)) as TextAsset;
        return textAsset.bytes;
#else
        var byteData = GameUtils.ReadFileAsBytes(GetScriptsFullPath(filepath));
        return byteData;
#endif
    }


    public void Require(string luaFile)
    {
        luaEnv.DoString(string.Format("require('{0}')", luaFile));
    }

    public string GetWindowFullPathByModuleName(string moduleName, string luaName)
    {
        return "view" + "." + moduleName + "." + luaName;
    }

    public string GetGameLogicFullPathByModuleName(string moduleName, string luaName)
    {
        return "gameLogic" + "." + moduleName + "." + luaName;
    }

    public LuaTable BindGameLogicScripts(string moduleName, string luaName)
    {
        string luaFile = GetGameLogicFullPathByModuleName(moduleName, luaName);
        return DoBind(luaFile);
    }

    public LuaTable BindWindowScripts(string moduleName, string luaName)
    {
        string luaFile = GetWindowFullPathByModuleName(moduleName, luaName);
        return DoBind(luaFile);
    }

    public LuaTable DoBind(string luaFile)
    {
        try
        {
            var luaTable = luaEnv.DoString(string.Format("return require('{0}').new()", luaFile));
            return luaTable[0] as LuaTable;
        }
        catch (Exception e)
        {
            Debug.LogError(e.Message);
            return null;
        }
    }

    public LuaEnv GetLuaEnv()
    {
        return luaEnv;
    }

}
